package com.rest.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.api.client.OAuthSigner;
import com.api.client.impl.ApiScribeRequest;
import com.api.client.impl.RequestLogger;
import com.api.client.model.ApiResponse;
import com.api.enums.ApiParameterType;
import com.api.enums.ApiVerb;
import com.api.model.ApiConsumer;
import com.api.model.ApiEnvironment;
import com.api.model.ApiParameter;
import com.api.model.ApiServiceMethod;
import com.api.model.ApiUser;
import com.rest.ApiClientRequest;
import com.rest.ApiServiceResponse;
import com.rest.RequestService;

public class RequestServiceImpl implements RequestService {

	@Override
	public ApiServiceResponse request(ApiClientRequest clientRequest) {

		ApiServiceMethod service = clientRequest.getService();
		ApiEnvironment environment = clientRequest.getEnvironment();
		String path = environment.getScheme() + "://" + environment.getHost() + service.getService() + service.getPath();
		ApiVerb verb = service.getVerb();

		Map<String, String> parameters = clientRequest.getValues();
		Map<String, String> queryParams = new HashMap<String, String>();
		Map<String, String> formParams = new HashMap<String, String>();

		List<ApiParameter> serviceParameters = service.getParameters();
		for (ApiParameter serviceParam : serviceParameters) {
			String paramName = serviceParam.getName();
			if (parameters.containsKey(paramName)) {
				String value = parameters.get(paramName);

				if (serviceParam.getType() == ApiParameterType.PATH) {
					path = path.replace("{" + paramName + "}", value);
				} else if (serviceParam.getType() == ApiParameterType.QUERY) {
					queryParams.put(paramName, value);
				} else if (serviceParam.getType() == ApiParameterType.FORM) {
					formParams.put(paramName, value);
				} else {
					if (verb == ApiVerb.POST) {
						formParams.put(paramName, value);
					} else {
						queryParams.put(paramName, value);
					}
				}
			}
		}

		ApiScribeRequest request = new ApiScribeRequest(verb.name(), path);
		request.addQueryValues(queryParams);
		request.addFormValues(formParams);

		ApiConsumer consumer = environment.getConsumer();
		OAuthSigner signer = new OAuthSigner(consumer.getKey(), consumer.getSecret());
		ApiUser user = clientRequest.getUser();
		request.sign(signer, user.getAccessKey(), user.getAccessSecret());

		RequestLogger.logRequest(request);

		long start = System.currentTimeMillis();
		ApiResponse response = request.send();
		long responseTime = System.currentTimeMillis() - start;
		RequestLogger.logResponse(response);

		return new ApiServiceResponse(response.getCode(), response.getBody(), responseTime);
	}
}
